package com.lancoo.edu.platform.operation.commons.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 时间转换工具
 * @author pky
 * @date 2021-08-25
 */
public class TimeUtil {

    private static SimpleDateFormat sf = null;
    private static SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd");
    private static SimpleDateFormat datetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static SimpleDateFormat month = new SimpleDateFormat(("yyyyMM"));
    private static SimpleDateFormat df = new SimpleDateFormat("HH:mm");// 时分格式
    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd/");
    public static Date getNowDate(){
        return new Date();
    }
    // ****************************当前时间相关****************************
    /**
     * 获得以 yyyy-MM-dd 为形式的当前时间字符串
     *
     * @return String
     */
    public static String getCurrentTimeByDay() {
        return date.format(new Date(System.currentTimeMillis()));
    }

    /**
     * 获得以 yyyy-MM-dd HH:mm:ss 为形式的当前时间字符串
     * @return String
     */
    public static String getCurrentTimeBySecond() {
        return datetime.format(new Date(System.currentTimeMillis()));
    }

    /**
     * 获得给定格式的当前时间字符串
     * @param give String 给定的时间格式
     * @return String
     */
    public static String getCurrentTime(String give) {
        SimpleDateFormat temp = new SimpleDateFormat(give);
        return temp.format(new Date(System.currentTimeMillis()));
    }

    /**
     * 时间戳转换成字符串
     */
    public static String getDateToString(long time) {
        Date d = new Date(time);
        sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sf.format(d);
    }

    /**
     * 将字符串转为时间戳
     */
    public static Long getStringToDate(String time) {
        sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try{
            return sf.parse(time).getTime();
        }
        catch(ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    // ****************************String转换为Date****************************
    /**
     * 将 String 转化成给定格式的 date
     * @param str 日期字符串
     * @param sfgs 日期格式
     * */
    public static Date pStringToDate(String str, String sfgs) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(sfgs);
            return sdf.parse(str);
        } catch (Exception e) {
            System.out.println("日期转换特定格式错误：" + e);
            return null;
        }
    }

    /**
     * 将String转化成date 格式为yyyy-MM-dd hh:mm:ss
     * @param str 字符串日期
     * @return Date 日期
     */
    public static Date pStringToDate(String str) {
        try {
            return datetime.parse(str);
        } catch (Exception e) {
            System.out.println("String转时间格式‘yyyy-MM-dd hh:mm:ss’错误");
            return null;
        }
    }

    // ****************************Date转换为String****************************
    /**
     * 转换成日期格式的字符串 格式为yyyy-MM-dd
     * @param o Date 日期
     * @return 字符串日期 yyyy-MM-dd
     */
    public static String dateFormat(Date o) {
        if (o == null) {
            return "";
        }
        return date.format(o);
    }

    /**
     * 转换成时间格式的字符串 格式为yyyy-MM-dd hh:mm:ss
     * @param o Date 日期
     * @return 字符串日期 yyyy-MM-dd hh:mm:ss
     */
    public static String dateTimeFormat(Date o) {
        if (o == null) {
            return "";
        }
        return datetime.format(o);
    }

    /**
     * 转换成时间格式字符串 格式为yyyyMM
     * @param o 要转换的日期
     * @return 字符串日期 yyyyMM
     */
    public static String monthFormat(Date o) {
        if(o == null) {
            return "";
        }
        return month.format(o);
    }

    /**
     * 转换成时间格式字符串 格式为 yyyy/MM/dd
     * @param date 要转换的日期
     * @return 字符串日期 yyyy/MM/dd
     */
    public static String dateForStr(Date date) {
        return simpleDateFormat.format(new Date());
    }

    /**
     * 转换成给定时间格式的字符串
     * @param d 要转换的日期
     * @param format 要转换的格式
     * @return String
     */
    public static String getDateFormat(Date d, String format) {
        return new SimpleDateFormat(format).format(d);
    }

    /**
     * 日期格式化(yyyy年MM月dd日)
     * @param date 要转换的日期
     * @return String
     * */
    public static String fDateCNYR(Date date) {
        return getDateFormat(date, "yyyy年MM月dd日");
    }

    /**
     * 日期格式化(yyyy年MM月dd日 HH:mm)
     * @param date 要转换的日期
     * @return String
     * */
    public static String fDateCNYRS(Date date) {
        return getDateFormat(date, "yyyy年MM月dd日 HH点");
    }

    /**
     * 日期格式化(yyyy年MM月dd日 HH:mm)
     * @param date 要转换的日期
     * @return String
     * */
    public static String fDateCNYRSF(Date date) {
        return getDateFormat(date, "yyyy年MM月dd日 HH:mm");
    }

    /**
     * 日期格式化(yyyy年MM月dd日 HH:mm:ss)
     * @param date 要转换的日期
     * @return String
     * */
    public static String fDateCNYRSFM(Date date) {
        return getDateFormat(date, "yyyy年MM月dd日 HH:mm:ss");
    }

    // ****************************时间格式的String转换为String****************************
    /**
     * 根据给定的时间格式字符串截取给定格式的字符串
     * @param d String 给定时间格式为yyyy-MM-dd HH:mm:ss
     * @param format String 给定的格式
     * @return String
     */
    public static String getDateFormat(String d, String format) throws ParseException {
        Date date = datetime.parse(d);
        return getDateFormat(date, format);
    }

    // ****************************时间格式的String转换为long****************************
    /**
     * 通过字符串获得long型时间
     * @param dateStr 日期字符串
     * @return long
     */
    public static long getDateFromStr(String dateStr) {
        long temp = 0L;
        Date date = null;
        try {
            date = datetime.parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
            return temp;
        }
        temp = date.getTime();
        return temp;
    }

    // ****************************Date转换为给定格式的Date****************************
    /**
     * 日期格式化（2014-03-04）
     * @param dat
     * @return Date
     * */
    public static Date fDate(Date dat) {
        String dateStr = date.format(dat);
        try {
            return date.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过开始时间和间隔获得结束时间。
     * @param start 开始时间
     * @param span 间隔
     * @return String
     */
    public static String getEndTime(String start, int span) {
        if (isNullOrNone(start) || span == 0) {
            return null;
        }
        long temp = getDateFromStr(start);
        temp += span * 60L * 1000L;
        return datetime.format(new Date(temp));
    }

    /**
     * 格式化字符串，将2013-10-20 00:00:00.000000简化为2013-10-20 00:00:00
     * @param str
     * @return String
     * @throws ParseException
     * */
    public static String getFormatStringDay(String str) throws ParseException {
        Date date = datetime.parse(str);
        return datetime.format(date);
    }

    /**
     * 判断是否为空
     * @param src
     * @return boolean
     */
    public static boolean isNullOrNone(String src) {
        if (null == src || "".equals(src)) {
            return true;
        }
        return false;
    }

    /**
     * 如果字符串长度大于25则截取前25个字符串后续改成省略号
     * @param str
     * @return String
     */
    public static String showCount(String str) {
        if (str != null) {
            if (str.length() > 25) {
                str = str.substring(0, 25);
                str = str + "...";
            }
        } else {
            str = "";
        }
        return str;
    }

    /**
     * 是否符合日期格式yyyy-MM-dd
     * @param day String 日期字符串
     * @return boolean
     */
    public static boolean isFormatDay(String day) {
        return day
                .matches("(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)");
    }

    /**
     * 是否符合时间格式HH:mm:ss
     * @param time
     *            String 时间字符串
     * @return boolean
     */
    public static boolean isFormatTime(String time) {
        return time
                .matches("(0[1-9]|1[0-9]|2[0-4]):(0[1-9]|[1-5][0-9]):(0[1-9]|[1-5][0-9])(\\.000000)?");
    }

    /**
     * 是否符合时间格式yyyy-MM-dd HH:mm:ss
     * @param time
     *            String 时间字符串
     * @return boolean
     */
    public static boolean isFormat(String time) {
        String[] temp = time.split(" ");
        return isFormatDay(temp[0]) && isFormatTime(temp[1]);
    }

    /**
     * 通过给定的年、月、周获得该周内的每一天日期
     * @param year
     *            int 年
     * @param month
     *            int 月
     * @param week
     *            int 周
     * @return List<Date> 七天的日期
     */
    public static List<Date> getDayByWeek(int year, int month, int week) {
        List<Date> list = new ArrayList<Date>();
        // 先滚动到该年.
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        // 滚动到月:
        c.set(Calendar.MONTH, month - 1);
        // 滚动到周:
        c.set(Calendar.WEEK_OF_MONTH, week);
        // 得到该周第一天:
        for (int i = 0; i < 6; i++) {
            c.set(Calendar.DAY_OF_WEEK, i + 2);
            list.add(c.getTime());
        }
        // 最后一天:
        c.set(Calendar.WEEK_OF_MONTH, week + 1);
        c.set(Calendar.DAY_OF_WEEK, 1);
        list.add(c.getTime());
        return list;
    }

    /**
     * 获得当前日期是本月的第几周
     *
     * @return int
     */
    public static int getCurWeekNoOfMonth() {
        Date date = new Date(System.currentTimeMillis());
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH);
    }

    /**
     * 获得当前日期是星期几
     *
     * @return int
     */
    public static int getCurWeekNo(String dat) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = format.parse(dat);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_WEEK);
    }

    /**
     * 获得当前的年份
     *
     * @return
     */
    public static int getCurrentYear() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 获得当前的月份
     *
     * @return
     */
    public static int getCurrentMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 获得当前的日期天
     *
     * @return
     */
    public static int getCurrentDay() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.DATE);
    }
    /**
     * 获取当月最后一天
     *
     * @param date 时间
     * @param format 格式
     * @return String
     * */
    public static String lastDayOfMoth(Date date, String format){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH,1);
        cal.add(Calendar.MONTH,1);
        cal.add(Calendar.DATE, -1);
        date =  cal.getTime();;
        SimpleDateFormat sf = new SimpleDateFormat(format);
        return sf.format(date);
    }
    /**
     * 获取当月最后一天
     *
     * @param date 时间
     * @param format 格式
     * @return String
     * */
    public static String firstDayOfMoth(Date date, String format){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, 0);
        date =  cal.getTime();;
        SimpleDateFormat sf = new SimpleDateFormat(format);
        return sf.format(date);
    }
    //****************************************************************
    /**
     * 转换成字符串方法，其中如果是Integer格式的返回0，如果是Double格式的返回0.0
     *
     * @param o
     * @return String
     */
    public static String toString(Object o) {
        if (o == null) {
            if (o instanceof Integer) {
                return "0";
            }
            if (o instanceof Double) {
                return "0.0";
            }
            return "";
        } else {
            return o.toString();
        }
    }

    /**
     * 清空字符串，如果为“”则转换成null
     *
     * @param src
     * @return String
     */
    public static String emptyString2Null(String src) {
        if (src != null) {
            if ("".equals(src)) {
                src = null;
            }
        }
        return src;
    }
    /**
     * 转化成可在hql中使用的字符串
     * 1,2 转为 '1','2'
     * */
    public static String formatIds(String ids){
        if(ids!=null&&ids!="")
        {
            String[] id = ids.split(",");
            StringBuffer idsStr = new StringBuffer();
            for(String str : id){
                idsStr.append("'"+str+"',");
            }
            return idsStr.toString().substring(0,idsStr.length()-1);
        }
        else
        {
            return "";
        }
    }
    /**
     * 获取当前日期前一天
     *
     * @param date
     * @return Date
     * */
    public static Date getSpecifiedDayBefore(Date date){
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int day = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day-1);
        date = c.getTime();
        return date;
    }
    /**
     * 比较两个日期的大小(前一个大于后一个则返回true，反之false)
     *
     * @param date1
     * @param date2
     * @return boolean
     * @author pky 2019-09-23 17:43:24
     * */
    public static boolean bjDate(Date date1, Date date2){
        if (date1.getTime() > date2.getTime()) {
            return true;
        }
        return false;
    }

    /**  
     * 计算两个日期bai之间相差的天数  
     * @param smdate 较小的时间 
     * @param bdate  较大的时间 
     * @return 相差天数 
     * @throws ParseException  
     */
    public static int daysBetween(Date smdate, Date bdate) {
        try {
            smdate = datetime.parse(datetime.format(smdate));
            bdate = datetime.parse(datetime.format(bdate));
            Calendar cal = Calendar.getInstance();
            cal.setTime(smdate);
            long time1 = cal.getTimeInMillis();
            cal.setTime(bdate);
            long time2 = cal.getTimeInMillis();
            long between_days = (time2 - time1) / (1000 * 3600 * 24);
            return Integer.parseInt(String.valueOf(between_days));
        }
        catch (Exception e) {
            System.out.println("时间转换失败" + e);
        }
        return -1;
    }

    /** 
     *字符串的日期格式的计算 
     */
    public static int daysBetween(String smdate, String bdate) throws Exception {
        try {
            Calendar cal = Calendar.getInstance();
            cal.setTime(datetime.parse(smdate));
            long time1 = cal.getTimeInMillis();
            cal.setTime(datetime.parse(bdate));
            long time2 = cal.getTimeInMillis();
            long between_days = (time2 - time1) / (1000 * 3600 * 24);
            return Integer.parseInt(String.valueOf(between_days));
        }
        catch (Exception e) {
            throw e;
        }
    }

    /**
     * 判断某时间是否处于某个时间区间
     * @param begin 开始时间
     * @param end 结束时间
     * @param targetTime 目标时间
     * @return
     */
    public static boolean checkBetween(String begin, String end, Date targetTime) {
        //初始化
        Date nowTime = null;
        Date beginTime = null;
        Date endTime = null;
        Date beginTime2 = null;
        Date endTime2 = null;
        try {
            //格式化当前时间格式
            nowTime = df.parse(df.format(targetTime));
            //定义第一个开始时间
            beginTime = df.parse(begin);
            //定义第二个开始时间
//            beginTime2 = df.parse("00:00");
            //定义第一个结束时间
            endTime = df.parse(end);
//            //定义第二个结束时间
//            endTime2 = df.parse("02:00");
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 设置当前时间
        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);
        // 设置第一个开始时间
        Calendar beginOne = Calendar.getInstance();
        beginOne.setTime(beginTime);
        // 设置第二个结束时间
        Calendar endOne = Calendar.getInstance();
        endOne.setTime(endTime);
        // 设置第一个开始时间
//        Calendar beginTwo = Calendar.getInstance();
//        beginTwo.setTime(beginTime2);
        // 设置第二个结束时间
//        Calendar endTwo = Calendar.getInstance();
//        endTwo.setTime(endTime2);
        // 处于开始时间之后，和结束时间之前的判断
//        if ((date.after(beginOne) && date.before(endOne)) || ((date.after(beginTwo) && date.before(endTwo)))) {
        if ((date.after(beginOne) && date.before(endOne)) ) {
            return true;
        }
        else {
            return false;
        }
    }

    /**
     * 两时间段相差几小时
     * @param beginTime 较小时间
     * @param endTime 较大时间
     * @return 小时
     * @throws Exception 转换异常
     */
    public static Long hourBetween(Date beginTime, Date endTime) {
        try {
            long nd = 1000 * 24 * 60 * 60;
            long nh = 1000 * 60 * 60;
            long nm = 1000 * 60;
            // long ns = 1000;
            // 获得两个时间的毫秒时间差异
            long diff = endTime.getTime() - beginTime.getTime();
            // 计算差多少天
            long day = diff / nd;
            // 计算差多少小时
            long hour = diff % nd / nh;
            // 计算差多少分钟
            long min = diff % nd % nh / nm;
            // 计算差多少秒//输出结果
            // long sec = diff % nd % nh % nm / ns;
            System.out.println(day + "天" + hour + "小时" + min + "分钟");
            return hour;
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 获取目标时间的前后几分钟、几天、几个月的时间

    /**
     * 前/后?分钟
     *
     * @param d 指定日期
     * @param minute 负数/前几分钟；正数/后几分钟
     * @return 前后几分钟的日期
     */
    public static Date rollMinute(Date d, int minute) {
        return new Date(d.getTime() + minute * 60 * 1000);
    }

    /**
     * 前/后?天
     *
     * @param d 日期
     * @param day 负数/前几天；正数/后几天
     * @return 前后几天的日期
     */
    public static Date rollDay(Date d, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(d);
        cal.add(Calendar.DAY_OF_MONTH, day);
        return cal.getTime();
    }


    /**
     * 前/后?月
     *
     * @param d 日期
     * @param mon 负数/前几月；正数/后几月
     * @return 前后几月的日期
     */
    public static Date rollMon(Date d, int mon) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(d);
        cal.add(Calendar.MONTH, mon);
        return cal.getTime();
    }

    /**
     * 前/后?年
     *
     * @param d 日期
     * @param year 负数/前几年；正数/后几年
     * @return 前后几年的日期
     */
    public static Date rollYear(Date d, int year) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(d);
        cal.add(Calendar.YEAR, year);
        return cal.getTime();
    }

    public static Date rollDate(Date d, int year, int mon, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(d);
        cal.add(Calendar.YEAR, year);
        cal.add(Calendar.MONTH, mon);
        cal.add(Calendar.DAY_OF_MONTH, day);
        return cal.getTime();
    }

    /**
     * 获取第二天凌晨0点毫秒数
     * @return
     */
    public static Date nextDayFirstDate() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取当前时间到明天凌晨0点相差秒数
     * @return 时间差（秒）
     */
    public static Long getSecsToEndOfCurrentDay()  {
        try {
            //将当前时间转为毫秒数
            Long secsOfNextDay  = nextDayFirstDate().getTime();
            //将时间转为秒数
            Long secsOfCurrentTime = System.currentTimeMillis();
            long distance = (secsOfNextDay - secsOfCurrentTime) / 1000;
            if (distance > 0){
                return distance;
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return 0L;
    }

}
